<script setup lang="ts">
import {computed, ref, watch} from "vue";
import {router} from "@/router";
import commonUtil, {EAction, ECode, iconFontAddress, PagePath} from "@/util/commonUtil";
import {useAppConfigStore} from "@/store/system/appConfigStore";
import xss from "xss";
import {timeAgoConvert} from "@/util/timeUtil";
import {createFromIconfontCN} from "@ant-design/icons-vue"
import Praise from "@/components/praise/index.vue";
import {userConfigStore} from "@/store/user/userConfigStore";
import {message} from "ant-design-vue";
import CommentBox from "../commentBox/index.vue"
import {addComment} from "@/api/comment/comment";
import {useSysEventStore} from "@/store/system/SysEventStore";
import Report from "@/components/report/index.vue"
import CommentReply from "../commentReply/index.vue"
import {loginConfigStore} from "@/store/user/loginConfigStore";
import {v4 as uuidV4} from 'uuid';
import {useSystemDictStore} from "@/store/system/systemDictStore";
import _ from "lodash";

const props = defineProps({
  // 父级组件传过来的评论列表
  comments: {
    type: Array<any>,
    default: () => []
  },
  userInfos: {
    type: Object
  },
  // 评论主体信息
  commentInfo: {
    type: Object
  },
  // 递归组件的嵌套层级，递归了1层、2层、3层、4层、5层，在最后一层可以禁止回复，拒绝无休止的评论
  level: {
    type: Number,
    default: 1,
  },
  marginLeft: {
    type: Number,
    default: 0,
  },
  // 控制最大评论层级
  maxReplyLevel: {
    type: Number,
    default: 5,
  },
  // 作者UID
  authorUid: {
    type: String,
    default: '',
  }
});
// xss白名单配置
const options = ref({
  whiteList: {
    div: ['class'],
    br: ['class'],
    a: ['href', 'title', 'target', 'style', 'class'],
    span: ['class', 'style'],
    h1: ['class'],
    h2: ['class'],
    h3: ['class'],
    h4: ['class'],
    ol: ['start'],
    pre: [],
    code: ['class'],
    p: ['class'],
    blockquote: ['class'],
    ul: ['class'],
    li: ['class'],
    img: ['class', 'src', 'alt', 'style'],
    hr: [],
    video: ['class', 'src', 'controls'],
    source: ['src', 'type']
  }
})
const toInfo = ref<any>({
  uid: "",
  commentUid: ""
})
const userInfo = ref<any>({})
const commentList = ref<any>(props.comments)
const componentShowMap = computed(() => useAppConfigStore().componentShowMap)
const reportInfo = ref<any>({})
const dialogReportVisible = ref<boolean>(false)
// 引入阿里图标库
const IconFont = createFromIconfontCN({
  scriptUrl: iconFontAddress,
});
const userTagDictList: any = computed(() => useSystemDictStore().SysUserTag)

watch(() => props.comments, () => {
  commentList.value = props.comments
})

function getTagName(tagId: string) {
  if (_.isEmpty(userTagDictList.value)) {
    return;
  }
  return userTagDictList.value.find((item: any) => item.dictValue == tagId)?.dictLabel
}

function getUserCenter(user: any) {
  let routeData = router.resolve({
    path: PagePath.UserCenterPath,
    query: {userUid: user.uid}
  });
  window.open(routeData.href, '_blank');
}

function convertContent(comment: any) {
  let toUser = comment.toUser
  let content = comment.content
  if (toUser && comment.toUid != comment.firstCommentUid) {
    let userCenterUrl = PagePath.UserCenterPath + "?userUid=" + toUser.uid
    content = "<span><a class='atUserLine' href='" + userCenterUrl + "' target='_blank'>@" + toUser.nickName + "</a></span>" + content;
  }
  content = commonUtil.replaceMinImg(content)
  if (document.body.clientWidth > 1000) {
    content = commonUtil.replaceMinIframe(content)
  }
  return content
}

function replyTo(item: any) {
  if (!validLogin()) {
    message.warning("登录后才能回复评论哦~")
    // 弹出登录框
    loginConfigStore().setLoginMessage(uuidV4())
    return
  }
  let userUid = item.userUid;
  toInfo.value.commentUid = item.uid
  toInfo.value.uid = userUid
}

// 校验是否登录
function validLogin() {
  let userInfo: any = userConfigStore().userInfo
  return userInfo.userName != undefined;
}

function submitBox(e: any) {
  let params: any = {};
  params.source = e.source;
  params.userUid = e.userUid;
  params.content = e.content;
  params.blogUid = e.blogUid;
  params.toUid = e.toCommentUid;
  params.toUserUid = e.toUserUid;
  addComment(params).then((response: any) => {
    if (response.code === ECode.SUCCESS) {
      let commentData = response.data
      toInfo.value.commentUid = ""
      let comments = useSysEventStore().commentList;
      commentData.user = userInfo.value;
      // 设置回复为空
      commentData.replyList = [];
      commentData.user = userConfigStore().userInfo
      updateCommentList(comments, commentData.toUid, commentData)
      useSysEventStore().setCommentList(comments)
      message.success("评论成功！");
      // 发送评论的领域事件
      let event = {
        "type": "action",
        "action": EAction.Comment,
        "resourceUid": e.blogUid,
        "resourceType": "BLOG",
        "time": new Date(),
      }
      useSysEventStore().setDomainEventMessage(event)
    } else {
      message.error(response.message)
    }
  })
}

// 追加内容
function updateCommentList(commentList: any, uid: any, targetComment: any) {
  if (commentList == undefined || commentList.length <= 0) {
    return;
  }
  for (let item of commentList) {
    let replyList = item.replyList;
    if (replyList == null) {
      replyList = []
    }
    if (item.uid == uid) {
      replyList.unshift(targetComment);
      item.replyList = replyList
      return;
    }
    for (let reply of replyList) {
      if (reply.uid == uid) {
        replyList.unshift(targetComment);
        item.replyList = replyList
        return;
      }
    }
  }
}

function report(item: any) {
  let report: any = {}
  report.reportType = "comment" // 评论
  report.reportUserUid = item.userUid // 被举报人id
  report.reportContentUid = item.uid
  report.reportContent = item.content
  reportInfo.value = report
  dialogReportVisible.value = true
}

function beforeClose(e: boolean) {
  dialogReportVisible.value = e
}

function showCancelCallBack() {
  toInfo.value.commentUid = ""
}

// 计算数组及其子数组的总长度
function calculateTotalLength(array: any[]): number {
  let totalLength = array.length;
  for (let item of array) {
    if (Array.isArray(item.replyList)) {
      totalLength += calculateTotalLength(item.replyList);
    }
  }
  return totalLength;
}

const totalCommentsLength = computed(() => calculateTotalLength(props.comments));

</script>

<template>
  <div class="momentList" id="momentList">
    <header class="commentListHeader flex justify-between">
      <div class="commentListHeaderLeft text-red-500">
        <IconFont type="icon-pinglun" class="text-base"/>
        <span class="font-semibold ml-1 mr-1">{{ totalCommentsLength }}</span>
        <span>条评论</span>
      </div>
      <div class="commentListHeaderRight">
        <!-- 头部右侧插槽 -->
        <slot name="header-right"/>
      </div>
    </header>
    <a-divider></a-divider>
    <!-- 评论列表主体 -->
    <ol class="flex flex-col gap-4">
      <!-- 评论列表 -->
      <li class="comment-dept-1 overflow-hidden" v-for="item in commentList" :key="item.uid">
        <a-comment>
          <template #avatar>
            <div class="commentAvatar relative" @click="getUserCenter(item.user)">
              <a-avatar v-if="item.user.photoUrl" size="large" class="h-10 w-10 flex items-center justify-center"
                        :src="item.user.photoUrl"
                        style="border: var(--vip-border)"/>
              <a-avatar v-else size="large" class="h-10 w-10 flex items-center justify-center"
                        style="border: var(--vip-border)">
                {{ item.user.nickName.slice(0, 1) }}
              </a-avatar>
              <sub class="badgeSup h-4 w-4 absolute bottom-1 right-0" v-if="item.user.userTag > 0">
                <img src="@/assets/vip/vip.svg" class="h-full w-full" alt="vipBadge">
              </sub>
            </div>
            <div class="h-[130%] w-full flex justify-center items-center borderLinkBox relative"
                 v-if="item.replyList && item.replyList.length > 0">
              <i class="borderLink not-italic h-full w-[1px]"></i>
            </div>
          </template>
          <template #author>
            <span class="font-semibold text-[14px] cursor-pointer">{{ item.user.nickName }}</span>
          </template>
          <template #actions>
            <span v-if="level < maxReplyLevel" @click="replyTo(item)">回复</span>
            <span v-if="componentShowMap.showUserReport" class="" @click="report(item)">举报</span>
            <span>
            <Praise :bizUid="item.uid" :resourceType="'5'"
                    :isPraiseValue="item.praiseInfo?item.praiseInfo.isPraise:false"
                    :isTreadValue="item.praiseInfo?item.praiseInfo.isPraise:false"
                    :praiseCountValue="item.praiseInfo?item.praiseInfo.praiseCount:0"
                    :treadCountValue="item.praiseInfo?item.praiseInfo.treadCount:0"
            ></Praise>
          </span>
          </template>
          <template #content>
            <span class="commentContent overflow-hidden" v-highlight v-html="xss(convertContent(item), options)"></span>
          </template>
          <template #datetime>
             <span class="userTag">
              <a-tag color="orange">
                <template #icon>
                  <IconFont type="icon-huibiao"/>
                </template>
                {{ getTagName(item.user.userTag) }}
              </a-tag>
            </span>
            <a-tag class="lv mr-2" color="purple" v-if="item.user.userLevel" :class="'lv'+ item.user.userLevel">
              <template #icon>
                <IconFont type="icon-huibiao"/>
              </template>
              Lv{{ item.user.userLevel }}
            </a-tag>
            <a-tag class="mr-2" v-if="authorUid == item.user.uid" color="magenta">作者</a-tag>
            <span v-if="item.user.userIpPossession" class="mr-2">IP属地:<i
                class="not-italic">{{ item.user.userIpPossession }}</i></span>
            <span class="mr-2">{{ timeAgoConvert(item.createTime) }}</span>
            <a-tag v-if="item.isTop == 1" color="red">置顶</a-tag>
          </template>
          <CommentReply v-if="item.replyList && item.replyList.length > 0"
                        :level="item.replyList.length"
                        :authorUid="authorUid"
                        :maxReplyLevel="maxReplyLevel"
                        :comments="item.replyList"
                        :commentInfo="commentInfo">
          </CommentReply>
        </a-comment>
        <div class="replyComment">
          <CommentBox v-if="toInfo.commentUid === item.uid"
                      class="replyCommentBox"
                      :toInfo="toInfo"
                      :userInfo="userInfo"
                      :id="item.uid"
                      @submit-box="submitBox"
                      @showCancel="showCancelCallBack"
                      :commentInfo="commentInfo">
          </CommentBox>
        </div>
      </li>
    </ol>
    <Report v-if="dialogReportVisible" :visible="dialogReportVisible" :reportInfo="reportInfo"
            @beforeClose="beforeClose"/>
  </div>
</template>

<style scoped lang="less">
.comment-dept-1 {
  padding: var(--gap-span);
  background: var(--bg);
  border-radius: var(--radius);
}

:deep(.ant-comment) {
  background-color: transparent;
}

:deep(.ant-comment-nested) {
  border-top: thin dashed hsl(var(--font-color) / .2);
}

:deep(.ant-comment-content-author) {
  display: flex;
  align-items: center;
  text-align: justify;
}

:deep(.ant-comment-content-author-name) > span {
  color: #2d79f3;
}

:deep(.ant-comment-actions) {
  display: flex;
}

:deep(.ant-comment-actions) li {
  display: flex;
}

:deep(.ant-tag >.anticon+span) {
  margin-inline-start: 0;
}

:deep(.ant-tag) {
  line-height: 14px;
}

:deep(.ant-divider) {
  margin: 16px 0;
}

.borderLink {
  border-left: 1px dashed hsl(var(--font-color) / .2);
}

.borderLinkBox::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 60%;
  height: 1px;
  border-bottom: 1px dashed hsl(var(--font-color) / .2);
}
</style>
